
#if defined(CON_ROBBO_BUILD) && defined (UTILITIES)
#include "RobboLito.h"
#include "RobboTripleBase.h"
#include "RobboTotalBase.h"

static char ENUMn[65] =
  { A1, A2, B1, B2, A3, A4, B3, B4, C1, C2, D1, D2, C3, C4, D3, D4,
    A8, A7, B8, B7, A6, A5, B6, B5, C8, C7, D8, D7, C6, C5, D6, D5,
    H1, H2, G1, G2, H3, H4, G3, G4, F1, F2, E1, E2, F3, F4, E3, E4,
    H8, H7, G8, G7, H6, H5, G6, G5, F8, F7, E8, E7, F6, F5, E6, E5, -1 };
static char ENUM_BI_PED[49] =
  { A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3,
    A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5,
    A6, B6, C6, D6, E6, F6, G6, H6, A7, B7, C7, D7, E7, F7, G7, H7, -1 };
static char ENUM_BLOCKED[41] =
  { A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3,
    A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5,
    A6, B6, C6, D6, E6, F6, G6, H6, -1 };
static char ENUM0[2] = { -2, -1 };

void VerifyTripleBase (typePOS* POSITION, int* p)
{
  int i, j, x, b;
  char* E[4];
  int wK,bK;
  int v[4];
  int s[4];
  uint64 add = 0;
  uint64 O;
  int triple, total;

  printf ("Start %d|%d|%d|%d\n", p[0], p[1], p[2], p[3]);
  POSITION->DYN->oo = POSITION->DYN->ep = 0;
  for (i = A1; i <= H8; i++)
    POSITION->sq[i] = 0;
  for (i = 0; i < 4; i++)
    {
      if (!p[i]) E[i] = ENUM0;
      else if (p[i] == wEnumP || p[i] == bEnumP)
	E[i] = ENUM_BI_PED; 
      else if (p[i] == BlockedPawn)
	E[i] = ENUM_BLOCKED;
      else
	E[i] = ENUMn;
    }
  for (wK = A1; wK <= H8; wK++)
    for (bK = A1; bK <= H8; bK++)
      {
	if ((AttK[wK] & SqSet[bK]) || (wK == bK))
	  continue;
	for (v[0] = 0; (s[0] = E[0][v[0]]) != -1; v[0]++)
	  for (v[1] = 0; (s[1] = E[1][v[1]]) != -1; v[1]++)
	    for (v[2] = 0; (s[2] = E[2][v[2]]) != -1; v[2]++)
	      for (v[3] = 0; (s[3] = E[3][v[3]]) != -1; v[3]++)
		{
		  if (wK == s[0] || bK == s[0] || wK == s[1] || bK == s[1] ||
		      wK == s[2] || bK == s[2] || wK == s[3] || bK == s[3])
		    continue;
		  if (p[1] && s[0] == s[1])
		    continue;
		  if (p[2] && (s[0] == s[2] || s[1] == s[2]))
		    continue;
		  if (p[3] && (s[0] == s[3] || s[1] == s[3] || s[2] == s[3]))
		    continue;
		  if (p[0] == BlockedPawn && p[0] == p[1] &&
                      s[1] == s[0] + 1 && FILE (s[0]) != FH)
                    continue;
		  if (p[0] == BlockedPawn && p[0] == p[2] &&
                      s[2] == s[0] + 1 && FILE (s[0]) != FH)
                    continue;
		  if (p[0] == BlockedPawn && p[0] == p[3] &&
                      s[3] == s[0] + 1 && FILE (s[0]) != FH)
                    continue;

		  if (p[1] == BlockedPawn && p[1] == p[0] &&
                      s[0] == s[1] + 1 && FILE (s[1]) != FH)
                    continue;
		  if (p[1] == BlockedPawn && p[1] == p[2] &&
                      s[2] == s[1] + 1 && FILE (s[1]) != FH)
                    continue;
		  if (p[1] == BlockedPawn && p[1] == p[3] &&
                      s[3] == s[1] + 1 && FILE (s[1]) != FH)
                    continue;

		  if (p[2] == BlockedPawn && p[2] == p[0] &&
                      s[0] == s[2] + 1 && FILE (s[2]) != FH)
                    continue;
		  if (p[2] == BlockedPawn && p[2] == p[1] &&
                      s[1] == s[2] + 1 && FILE (s[2]) != FH)
                    continue;
		  if (p[2] == BlockedPawn && p[2] == p[3] &&
                      s[3] == s[2] + 1 && FILE (s[2]) != FH)
                    continue;

		  if (p[3] == BlockedPawn && p[3] == p[0] &&
                      s[0] == s[3] + 1 && FILE (s[3]) != FH)
                    continue;
		  if (p[3] == BlockedPawn && p[3] == p[1] &&
                      s[1] == s[3] + 1 && FILE (s[3]) != FH)
                    continue;
		  if (p[3] == BlockedPawn && p[3] == p[2] &&
                      s[2] == s[3] + 1 && FILE (s[3]) != FH)
                    continue;

		  if (p[0] == BlockedPawn &&
		      (wK == s[0] + 8 || bK == s[0] + 8 ||
		       (p[1] && s[0] + 8 == s[1]) ||
		       (p[2] && s[0] + 8 == s[2]) ||
		       (p[3] && s[0] + 8 == s[3])))
		    continue;
		  if (p[1] == BlockedPawn &&
		      (wK == s[1] + 8 || bK == s[1] + 8 ||
		       (p[0] && s[1] + 8 == s[0]) ||
		       (p[2] && s[1] + 8 == s[2]) ||
		       (p[3] && s[1] + 8 == s[3])))
		    continue;
		  if (p[2] == BlockedPawn &&
		      (wK == s[2] + 8 || bK == s[2] + 8 ||
		       (p[0] && s[2] + 8 == s[0]) ||
		       (p[1] && s[2] + 8 == s[1]) ||
		       (p[3] && s[2] + 8 == s[3])))
		    continue;
		  if (p[3] == BlockedPawn &&
		      (wK == s[3] + 8 || bK == s[3] + 8 ||
		       (p[0] && s[1] + 8 == s[0]) ||
		       (p[1] && s[3] + 8 == s[1]) ||
		       (p[2] && s[3] + 8 == s[2])))
		    continue;
		  wBitboardQ = wBitboardR = wBitboardBL = 
		    wBitboardBD = wBitboardN = wBitboardP = 0;
		  bBitboardQ = bBitboardR = bBitboardBL = 
		    bBitboardBD = bBitboardN = bBitboardP = 0;
		  POSITION->wKsq = wK;
		  POSITION->bKsq = bK;
		  wBitboardK = SqSet[wK];
		  bBitboardK = SqSet[bK];
		  POSITION->sq[wK] = wEnumK;
		  POSITION->sq[bK] = bEnumK;
		  for (j = 0; j < 4; j++)
		    {
		      x = s[j];
		      if (p[j])
			POSITION->sq[x] = p[j];
		      if (p[j] == BlockedPawn)
			{
			  POSITION->sq[x] = wEnumP;
			  POSITION->sq[x + 8] = bEnumP;
			}
		      if (p[j] == wEnumB)
			{
			  if (SqSet[x] & LIGHT)
			    POSITION->sq[x] = wEnumBL;
			  else
			    POSITION->sq[x] = wEnumBD;
			}
		      if (p[j] == bEnumB)
			{
			  if (SqSet[x] & LIGHT)
			    POSITION->sq[x] = bEnumBL;
			  else
			    POSITION->sq[x] = bEnumBD;
			}
		      switch (p[j])
			{
			  case wEnumQ:
			    wBitboardQ |= SqSet[x];
			    break;
			  case wEnumR:
			    wBitboardR |= SqSet[x];
			    break;
			  case wEnumB:
			    if (SqSet[x] & LIGHT)
			      wBitboardBL |= SqSet[x];
			    if (SqSet[x] & DARK)
			      wBitboardBD |= SqSet[x];
			    break;
			  case wEnumN:
			    wBitboardN |= SqSet[x];
			    break;
			  case wEnumP:
			    wBitboardP |= SqSet[x];
			    break;
			  case bEnumQ:
			    bBitboardQ |= SqSet[x];
			    break;
			  case bEnumR:
			    bBitboardR |= SqSet[x];
			    break;
			  case bEnumB:
			    if (SqSet[x] & LIGHT)
			      bBitboardBL |= SqSet[x];
			    if (SqSet[x] & DARK)
			      bBitboardBD |= SqSet[x];
			    break;
			  case bEnumN:
			    bBitboardN |= SqSet[x];
			    break;
			  case bEnumP:
			    bBitboardP |= SqSet[x];
			    break;
			  case BlockedPawn:
			    wBitboardP |= SqSet[x];
			    bBitboardP |= SqSet[x + 8];
			    break;
			}
		    }
		  wBitboardOcc = wBitboardK | wBitboardQ | wBitboardR |
		    wBitboardBL | wBitboardBD | wBitboardN | wBitboardP;
		  bBitboardOcc = bBitboardK | bBitboardQ | bBitboardR |
		    bBitboardBL | bBitboardBD | bBitboardN | bBitboardP;
		  O = POSITION->OccupiedBW = wBitboardOcc | bBitboardOcc;
#ifndef MAGIC_BITBOARDS
		  POSITION->OccupiedL45 = 0;
		  POSITION->OccupiedL90 = 0;
		  POSITION->OccupiedR45 = 0;
		  POSITION->wtm = FALSE; /* TRUE / FALSE */
		  while (O)
		    {
		      b = BSF (O);
		      BitClear (b, O);
		      POSITION->OccupiedL45 |= SqSet[Left45[b]];
		      POSITION->OccupiedL90 |= SqSet[Left90[b]];
		      POSITION->OccupiedR45 |= SqSet[Right45[b]];
		    }
#endif
		  Mobility (POSITION);
		  if (IS_ILLEGAL)
		    goto END;
		  if (!TRIPLE_VALUE (POSITION, &triple)) /* evade => ep? BPp */
		    goto END;
		  if (!RobboTotalBaseScore (POSITION, &total))
		    printf ("TotalBase failed\n");
		  add++;
		  if ((add & 0xfffff) == 0)
		    printf ("Done %lld\n", add);
		  if (total == dPATT)
		    total = 0;
		  else if (total == dVITT)
		    total = 1;
		  else
		    total = -1;
		  if (total != triple)
		    printf ("VerBad %lld %d+%d %d|%d|%d|%d trip:%d tot:%d\n",
			    add, wK, bK, s[0], s[1], s[2], s[3], triple, total);
		  if (total != triple)
		    DrawBoard (POSITION);
		  if (total != triple)
		    exit(1);
		END:
		  for (j = 0; j < 4; j++)
		    if (p[j])
		      POSITION->sq[s[j]] = 0;
		  for (j = 0; j < 4; j++)
		    if (p[j] == BlockedPawn)
		      POSITION->sq[8 + s[j]] = 0;
		  POSITION->sq[wK] = POSITION->sq[bK] = 0;
		}
      }
  printf ("AllDone %lld %d|%d|%d|%d\n", add, p[0], p[1], p[2], p[3]);
}
#endif
